
/*

Design Pattern Automation Toolkit.
Application to create applications with emphasis on Design patterns.
And support for round trip engineering.
Copyright (C) 2004 Vineeth Neelakant. nvineeth@gmail.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
using System;
using System.Collections;
using System.Reflection;
using System.Windows.Forms;
using DesignPatternDefinitions;

namespace DotNetReverseEngineering
{
	using UIForms;
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	[ReverseEngineerInfo("All .NET aware languages","Native Application")]
	public class DotNetReverseEngineer : IReverseEngineer
	{
		// mapping between component name and the classes list(arraylist)
		Hashtable compToClass = new Hashtable();
		ArrayList components = new ArrayList();
		string projectTitle=".NetProject";
		public static string DefaultNamespace = "DefaultNamespace";

		public IProject GetProject()
		{
			//ideally, the following steps shld be done >>
			//Step1: Tell the user to select all the source files.
			//step2: Compile all the source files into a Dll, 
			//       if errors are found display it to the user and exit.
			
			//Step 3:Now the IProject concrete class and pass it on to the user.
			
			DotNetReverseEnggForm dialog = new DotNetReverseEnggForm();
			if( dialog.ShowDialog()== DialogResult.Cancel)
			{
				MessageBox.Show("Aborted by user!");
				return null;
			}
			
			string fname = dialog.FileName;
			this.AnalyzeAssembly(fname);
			IProject project = new RevEnggProjectInfo();
			project.ProjectName=this.projectTitle;
			project.Components=this.components;
			return project;
		}

        public string Description
        {
            get { return ".NET Assembly (DLL) Reverse Engineer"; }
        }

		private void AnalyzeAssembly(string path )
		{

			Assembly a;
			string nspace;//namespace.
			try{
			a = Assembly.LoadFrom(path);
			}
			catch{
				MessageBox.Show("The supplied path doesnot contain a valid dll","Error!");
				return;
			}
			Type[] mytypes = a.GetTypes();
			this.projectTitle = a.GetName().Name;
			
			foreach(Type t in mytypes)
			{
				if( t.IsClass || t.IsInterface)
				{
					nspace = t.Namespace;
					if(nspace==null)
						nspace = DefaultNamespace;
					if(nspace==string.Empty)
						nspace = DefaultNamespace;

					/* Add the component to hashtable 
					 * Here the component key is initialized.
					 * */
					if( !compToClass.Contains(nspace) )
						compToClass.Add(nspace,new ArrayList());
					
					IClass cls = new RevEnggClassInfo(t);
					cls.ComponentName = nspace;
					ArrayList classes = compToClass[nspace] as ArrayList;
					classes.Add(cls);
					compToClass[nspace]=classes;
				}
			}
			
			foreach (string comp in compToClass.Keys)
			{
				IProjectComponent component = new RevEnggComponentInfo();
				component.ComponentName=comp;
				component.ComponentSummary = "Generated by reflecting the assembly";
				component.ComponentAuthor = "DpaToolkit";
				component.Classes = this.compToClass[comp] as ArrayList;
				this.components.Add(component);
			}

		}
		}
}
